package com.bright.tactiviti.activiti.controller;

import com.bright.tactiviti.activiti.entity.ActModel;
import com.bright.tactiviti.activiti.entity.ActProcess;
import com.bright.tactiviti.activiti.service.ActModelService;
import com.bright.tactiviti.activiti.service.ActProcessService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;

@Slf4j
@RestController
@Api("模型接口管理")
@RequestMapping("/tactiviti/actmodel")
@Transactional
public class ActModelController {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ActModelService actModelService;

    @Autowired
    private ActProcessService processService;
    /**
     * 创建一个新模型
     */
    @PostMapping("/create")
    public void addModel(@ModelAttribute ActModel actModel){
        //初始化一个模型
        Model model = repositoryService.newModel();

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME,actModel.getName());
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION,actModel.getDescription());
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION,actModel.getVersion());

        model.setName(actModel.getName());
        model.setKey(actModel.getModelKey());
        model.setMetaInfo(modelNode.toString());

        //保存模型
        repositoryService.saveModel(model);
        String id = model.getId();

        // 完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        ObjectNode properties = objectMapper.createObjectNode();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.replace("stencilset", stencilSetNode);
        properties.put("process_id", actModel.getModelKey());
        editorNode.replace("properties",properties);
        try{
            repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        }catch (UnsupportedEncodingException e){
            log.error(e.toString());
            System.out.print("模型添加失败");
        }

        actModel.setId(id);
        actModel.setVersion(model.getVersion());
        try {
            actModelService.saveEntity(actModel);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print("保存出错");
        }
        System.out.print("模型添加成功");
    }

    /**
     * 发布模型
     */
    @GetMapping("/deploy/{id}")
    @ApiModelProperty("发布模型")
    public void deploy(@PathVariable String id){
        //获取模型
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
        if (bytes == null) {
            System.out.print("模型数据为空，请先成功设计流程并保存");
        }

        try{
            JsonNode modelNode = new ObjectMapper().readTree(bytes);
            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            if(model.getProcesses().size()==0){
                System.out.print("模型不否和要求，至少有一条主线");
            }
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            //部署发布模型流程
            String processName = modelData.getName() + ".bpmn20.xml";
            Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName,new String(bpmnBytes,"utf-8"))
                    .deploy();
            //设置流程分类，保存扩展流程值数据库
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
            ActModel actModel = actModelService.get(id);
            list.forEach(dt -> {
                ActProcess actProcess = new ActProcess();
                actProcess.setId(dt.getId());
                actProcess.setName(modelData.getName());
                actProcess.setProcessKey(modelData.getKey());
                actProcess.setDeploymentId(deployment.getId());
                actProcess.setDescription(actModel.getDescription());
                actProcess.setVersion(dt.getVersion());
                actProcess.setXmlName(dt.getResourceName());
                actProcess.setLatest(true);
                try {
                    processService.saveEntity(actProcess);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.print("保存出错");
                }
            });
        }catch (Exception e){
            log.error(e.toString());
            System.out.print("部署失败");
        }
        System.out.print("部署成功");
    }
}
